/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package gride.plugin.editor;

import gride.project.GrideScript;
import gride.groovy.Regex;
import java.awt.Color;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import javax.swing.JEditorPane;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;

/**
 *
 * @author lukasz
 */
public class EditorTab extends JScrollPane
{
    // <editor-fold defaultstate="expanded" desc="Private Members">
    
    private GrideScript file;
    private JEditorPane editor;
    private String savedContents;
    
    // </editor-fold>
    
    // <editor-fold defaultstate="expanded" desc="Constructors">

    /**
     * 
     * @param file
     * @throws java.io.IOException
     */
    public EditorTab(GrideScript file) throws IOException
    {
        this.file = file;

        // read the file contents into a string
        savedContents = readFileContents(file.getSourcefile());

        // create an editor and add to the scroll
        editor = new JEditorPane();
        this.setViewportView(editor);

        // set the editor content type and fill with file contents
        editor.setContentType(getContentType(file.getSourcefile().getName()));
        editor.setText(savedContents);
        
        final Color defaultSelectionColor = editor.getSelectionColor();

        // add a caret listener restoring selection color to default
        // (color selection ussed to highlight lines)
        editor.addCaretListener(new CaretListener()
        {
            public void caretUpdate(CaretEvent e)
            {
                editor.setSelectionColor(defaultSelectionColor);
            }
        });

        // also required because cared updates only on mouse release
        editor.addMouseListener(new MouseAdapter()
        {
            @Override
            public void mousePressed(MouseEvent e)
            {
                editor.setSelectionColor(defaultSelectionColor);
            }
        });
    }

    // </editor-fold>

    // <editor-fold defaultstate="expanded" desc="Getters/Setters">

    /**
     *
     * @return
     */
    public GrideScript getFile()
    {
        return file;
    }

    /**
     *
     * @return
     */
    public Document getDocument()
    {
        return editor.getDocument();
    }

    /**
     *
     * @param text
     */
    public void setText(String text)
    {
        editor.setText(text);
    }

    // </editor-fold>

    // <editor-fold defaultstate="expanded" desc="Public Methods">

    /**
     *
     */
    public void saveFile()
    {
        try
        {
            File f = file.getSourcefile();

            // just in case, recreate the file's directory
            f.mkdirs();

            // write the contents of the tab into the file
            FileWriter writer = new FileWriter(f.getAbsolutePath());
            writer.write(editor.getText());
            writer.close();

            savedContents = editor.getText();
        }
        catch (IOException e)
        {
            JOptionPane.showMessageDialog(null, "Couldn't save file!", "Error",
                                          JOptionPane.ERROR_MESSAGE);
            return;
        }
    }

    /**
     *
     * @return
     */
    public boolean isModified()
    {
        // check if the saved contents are different from the ones in editor
        try
        {
            return !savedContents.equals(editor.getDocument().getText(0,
                                         editor.getDocument().getLength()));
        }
        catch (BadLocationException ex)
        {
            // better say that it's modified
            return true;
        }
    }

    /**
     * Highlights the given line in the editor with the given color
     * @param line
     * @param color
     */
    public void highlightLine(int line, Color color)
    {
        editor.setSelectionStart(getLinePosition(editor.getText(), line));
        editor.setSelectionEnd(getLinePosition(editor.getText(), line + 1));

        editor.setSelectionColor(color);
        editor.requestFocus();
    }


    @Override
    public void requestFocus()
    {
        editor.requestFocus();
    }

    // </editor-fold>

    // <editor-fold defaultstate="expanded" desc="Private Methods">

    /**
     * Returns a String containing the contents of the given file
     * @param file
     * @return
     * @throws java.io.IOException
     */
    private String readFileContents(File file) throws IOException
    {
        StringBuilder fileContents = new StringBuilder();
        char[] buf = new char[1024];

        FileReader reader = new FileReader(file);

        int charsRead = 0;
        while ((charsRead = reader.read(buf)) != -1) {
            fileContents.append(buf, 0, charsRead);
        }

       return fileContents.toString();
    }


    // works out the content type based on file extension
    // for unknown extensions, returns text/plain
    private String getContentType(String filename)
    {
        String fileExtension = Regex.getFileExtension(filename);

        if (fileExtension.equals("groovy"))
            return "text/groovy";
        else if (fileExtension.equals("java"))
            return "text/java";
        else
            return "text/plain";
    }


    /**
     * Calculates the offset of the beginning of the given line in text
     * @param text
     * @param line
     * @return
     */
    private int getLinePosition(String text, int line)
    {
        int index = 0;
        int l = 1;

        // move one character at a time and keep count of newlines
        while (index < text.length())
        {
            if (text.charAt(index) == '\n')
                l++;

            if (l == line)
                return index + 1;

            index++;
        }

        return index;
    }

    // </editor-fold>
}
